2019年6月25日
Jerry
11776
2020年12月3日
人生不止眼前的苟且,代码也不止数据的增删改查,也有有趣的网络编程。如何用C语言做一个简单的服务器和客户端,实现一个聊天室程序呢?这里就简单的写一下博主的实现。
一、程序需求
实现一个简单的服务器,包括以下功能:
- 可以监听并且与多个客户端建立TCP链接。
- 可以接收客户端发来的消息,并发送给所有的客户端。
- 可查询所有的客户端链接。
实现客户端有如下功能:
- 输入服务器端口号,与服务器端建立链接。
- 发送消息给服务器。
- 接收并打印服务器发来的消息。
二、实现分析
借用百度的一张图,这个流程很好的解释了socket编程的根本:
服务器端的处理流程思路:
- 创建socket套接字
- 绑定ip与端口号
- 创建监听线程,等待客户端链接
- 接收到一个客户端链接则创建一个线程进行消息接收处理
- 客户端关闭,关闭相关进程
- 服务器关闭
客户端的处理流程思路:
- 创建socket套接字
- 输入端口号链接服务器
- 创建线程处理服务器消息
- 接收控制台输入发送给服务器
- 客户端关闭
socket的基本api:
包含在在头文件“winsock2.h”,官网说明地址: https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/
三、基本的socket API
1、创建一个socket套接字:
/*
domain:协议域、地址域或协议族。常用的协议族有:AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX)、AF_ROUTE等等
type:socket类型。常用的socket类型有:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等
protocol:指定使用的协议。常用的协议有:IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等等
返回值:成功返回一个非负整数的fd,失败则返回-1
*/
int socket(int domain, int type, int protocol);
2、绑定套接字
/*
sockfd:socket文件描述符,即socket()的返回值
addr:指向sock地址的指针
addrlen:sock地址的长度
返回值:成功返回0,失败返回-1
*/
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
3、监听套接字
/*
sockfd:被监听的套接字
backlog:最大等待队列数量
返回值:成功返回0,失败返回-1
*/
int listen(int sockfd, int backlog);
4、连接socket套接字
/*
sockfd:客户端的套接字
addr:服务器的地址
addrlen:服务器的地址的长度
返回值:成功返回0,失败返回-1
*/
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
5、接受socket连接请求
/*
sockfd:被监听的套接字
addr:返回客户端的地址,可为NULL
addrlen:指定客户端的地址的长度,可为NULL
返回值:成功返回已连接的新套接字描述符connfd,失败返回-1
*/
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
6、socket接收数据
/*
sockfd:从这个socket接收数据
buf:用来保存接收到的数据
len:指定buf的长度,表示最多接收这么多个字节的数据
flags:flags,指定对应的选项,一般置为0
返回值:成功返回接收到的数据大小,返回0表示对方不再发送数据(可以理解为关闭了连接),出错返回-1
*/
int recv(int sockfd, void *buf, int len, int flags);
7、socket发送数据
/*
sockfd:向这个socket发送数据
buf:发送buf指向的数据
len:指定buf的长度,指定要发送的数据大小
flags:flags,指定对应的选项,一般置为0
返回值:成功返回已发送的数据大小,失败则返回-1
*/
int send(int sockfd, void *buf, int len, int flags);
8、从udp socket接收数据
/*
sockfd:输入参数,从该socket接收数据
buf:输出参数,将接收的数据存放在buf上
len:输入参数,指定buf的长度
flags:输入参数,flags,指定对应的选项,一般置为0
addr:输出参数,保存该数据的发送方地址
addrlen:输入参数,指定发送方地址的长度
返回值:成功返回接收到的数据大小,失败则返回-1
*/
int recvfrom(int sockfd, void *buf, int len, int flags, struct sockaddr *addr, socklen_t *addrlen);
9、向udp socket发送数据
/*
sockfd:输入参数,向该socket发送数据
buf:输入参数,发送buf指向的数据
len:输入参数,指定buf的长度
flags:输入参数,flags,指定对应的选项,一般置为0
addr:输入参数,指定接收方的地址
addrlen:输入参数,指定接收方的地址的长度
返回值:成功返回发送的数据大小,失败则返回-1
*/
int sendto(int sockfd, void *buf, int len, int flags, struct sockaddr *addr, socklen_t addrlen);
10、关闭socket
/*
fd: 要关闭的socketID
*/
int close(int fd);
四、最终实现效果
服务器端:
客户端:
1、建立多个链接
2、发送消息
3、客户端断开链接
4、服务器关闭
搞起!
原创文章,转载请注明出处:
https://jerrycoding.com/article/socket-chat
《课设小程序》
0
微信
支付宝